package com.kk.solr.service.impl;

import com.kk.solr.service.SolrService;
import com.kk.solr.service.dto.SolrFileQueryCriteria;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.utils.FileUtil;
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.client.WebClient;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@Service
@Slf4j
public class SolrServiceImpl implements SolrService {

    private static final String DATA_IMPORT_URL =
            "%s/dataimport?" +
                    "clean=false&" +
                    "commit=true&" +
                    "intent=on&" +
                    "name=dataimport&" +
                    "wt=json&" +
                    "verbose=false&" +
                    // 使用full-import来模拟delta-import，在配置文件中根据entity参数添加newerThan逻辑
                    "command=full-import&" +
                    "entity=%s&" +
                    "_=%d";

    private static final String ENTITY_FULL_IMPORT = "doc_full";
    private static final String ENTITY_DELTA_IMPORT = "doc_delta";

    private SolrClient mSolrClient;
    @Value("${spring.data.solr.host}")
    private String mSolrHost;
    @Value("${file.path}")
    private String path;
    private static final Duration INDEX_WAIT_DURATION = Duration.of(10, ChronoUnit.SECONDS);

    @Autowired
    public SolrServiceImpl(SolrClient solrClient) {
        mSolrClient = solrClient;
    }

    @Override
    public SolrDocumentList querySolrAdvance(String collection,
                                             SolrFileQueryCriteria criteria,
                                             Pageable pageable) throws IOException, SolrServerException {
        String field = criteria.getType();
        String content = criteria.getValue();
        SolrQuery params = new SolrQuery();
        //查询条件, 这里的 q 对应 下面图片标红的地方
        params.set("q", content);
        //过滤条件
        // params.set("fq", "product_price:[100 TO 100000]");
        //排序
        // params.addSort("id", SolrQuery.ORDER.asc);
        //分页
        params.setStart(pageable.getPageNumber());
        params.setRows(pageable.getPageSize());
        //默认域
        params.set("df", field);
        //只查询指定域
        // params.set("fl", content + ",content,id,title,author");
        //高亮
        //打开开关
        params.setHighlight(true);
        //指定高亮域
        params.addHighlightField("id");
        params.addHighlightField(field);
        params.addHighlightField("title");
        params.addHighlightField("content");
        params.addHighlightField("author");

        params.addHighlightField("productName");
        params.addHighlightField("productDesc");

        //设置前缀
        params.setHighlightSimplePre("<font color=#FF0000>");
        //设置后缀
        params.setHighlightSimplePost("</font>");

        QueryResponse queryResponse = mSolrClient.query(collection, params);

        SolrDocumentList results = queryResponse.getResults();
        //获取高亮显示的结果, 高亮显示的结果和查询结果是分开放的
        Map<String, Map<String, List<String>>> highlight = queryResponse.getHighlighting();
        for (SolrDocument result : results) { // 将高亮结果合并到查询结果中
            result.remove("keyword");
            highlight.forEach((k, v) -> {
                if (result.get("id").equals(k)) {
                    v.forEach((k1, v1) -> {
                        if (!k1.equals("keyword")) {
                            result.setField(k1, v1); // 高亮列合并如结果
                        }
                    });
                }
            });
        }
        return results;
    }

    @Override
    public boolean reIndex(String collection) throws IOException, SolrServerException {
        // 删除原有索引
        mSolrClient.deleteByQuery(collection, "*:*");
        mSolrClient.commit(collection);
        // 重新创建索引
        mono(collection, ENTITY_FULL_IMPORT);
        return true;
    }

    @Override
    public boolean deltaIndex(String collection) {
        mono(collection, ENTITY_DELTA_IMPORT);
        return false;
    }

    @Override
    public boolean upload(MultipartFile[] multipartFiles) {
        boolean success = true;
        for (MultipartFile multipartFile : multipartFiles) {
            File file = FileUtil.upload(multipartFile, path);
            success = success && file != null && file.exists();
            log.info("add file:{}, contentType:{}", multipartFile.getOriginalFilename(),
                    multipartFile.getContentType());
        }
        return success;
    }

    private void mono(String collection, String entity) {
        String fileDataImport = String.format(Locale.US,
                DATA_IMPORT_URL,
                collection,
                entity,
                System.currentTimeMillis());

        WebClient.create(mSolrHost)
                .get()
                .uri(fileDataImport)
                .retrieve()
                .bodyToMono(String.class)
                .doOnSuccess(result -> log.info("{} index success:{}", entity, result))
                .doOnError(throwable -> log.info("{} index failed:{}", entity, throwable.getMessage()))
                .block(INDEX_WAIT_DURATION);
    }
}
